using System;
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;
using dnAnalytics.Math;
using dnAnalytics.LinearAlgebra;
using dnAnalytics.Exceptions;

namespace dnAnalytics.UnitTests.LinearAlgebra
{
    [TestFixture]
    [Category("Managed")]
    public class VectorBuilderTest
    {
        [Test]
        public void CreateVectorSize()
        {
            Vector vector = VectorBuilder.CreateVector(10);
            Assert.AreEqual(vector.Count, 10);

            if (Settings.DefaultVectorType == VectorType.Dense)
            {
                Assert.AreEqual(typeof(DenseVector), vector.GetType());
            }

            if (Settings.DefaultVectorType == VectorType.Sparse)
            {
                Assert.AreEqual(typeof(SparseVector), vector.GetType());
            }

            vector = VectorBuilder.CreateVector(10, VectorType.Dense);
            Assert.AreEqual(vector.Count, 10);
            Assert.AreEqual(typeof(DenseVector), vector.GetType());

            vector = VectorBuilder.CreateVector(10, VectorType.Sparse);
            Assert.AreEqual(vector.Count, 10);
            Assert.AreEqual(typeof(SparseVector), vector.GetType());

            vector = VectorBuilder.CreateVector(10, VectorType.Dense, true);
            Assert.AreEqual(vector.Count, 10);
            Assert.AreEqual(typeof(DenseVector), vector.GetType());

            vector = VectorBuilder.CreateVector(10, VectorType.Sparse, true);
            Assert.AreEqual(vector.Count, 10);
            Assert.AreEqual(typeof(SparseVector), vector.GetType());

            vector = VectorBuilder.CreateVector(10, VectorType.Dense, false);
            Assert.AreEqual(vector.Count, 10);
            Assert.AreEqual(typeof(DenseVector), vector.GetType());

            vector = VectorBuilder.CreateVector(10, VectorType.Sparse, false);
            Assert.AreEqual(vector.Count, 10);
            Assert.AreEqual(typeof(SparseVector), vector.GetType());
        }

        [Test]
        public void CreateVectorValue()
        {
            Vector vector = VectorBuilder.CreateVector(10, 5.5);
            Assert.AreEqual(vector.Count, 10);
            if (Settings.DefaultVectorType == VectorType.Dense)
            {
                Assert.AreEqual(typeof(DenseVector), vector.GetType());
            }

            if (Settings.DefaultVectorType == VectorType.Sparse)
            {
                Assert.AreEqual(typeof(SparseVector), vector.GetType());
            }

            for (int i = 0; i < vector.Count; i++)
            {
                Assert.AreEqual(5.5, vector[i]);
            }

            vector = VectorBuilder.CreateVector(10, 5.5, VectorType.Dense);
            Assert.AreEqual(vector.Count, 10);
            Assert.AreEqual(typeof(DenseVector), vector.GetType());
            for (int i = 0; i < vector.Count; i++)
            {
                Assert.AreEqual(5.5, vector[i]);
            }

            vector = VectorBuilder.CreateVector(10, 5.5, VectorType.Sparse);
            Assert.AreEqual(vector.Count, 10);
            Assert.AreEqual(typeof(SparseVector), vector.GetType());
            for (int i = 0; i < vector.Count; i++)
            {
                Assert.AreEqual(5.5, vector[i]);
            }

            vector = VectorBuilder.CreateVector(10, 5.5, VectorType.Dense, true);
            Assert.AreEqual(vector.Count, 10);
            Assert.AreEqual(typeof(DenseVector), vector.GetType());
            for (int i = 0; i < vector.Count; i++)
            {
                Assert.AreEqual(5.5, vector[i]);
            }

            vector = VectorBuilder.CreateVector(10, 5.5, VectorType.Sparse, true);
            Assert.AreEqual(vector.Count, 10);
            Assert.AreEqual(typeof(SparseVector), vector.GetType());
            for (int i = 0; i < vector.Count; i++)
            {
                Assert.AreEqual(5.5, vector[i]);
            }

            vector = VectorBuilder.CreateVector(10, 5.5, VectorType.Dense, false);
            Assert.AreEqual(vector.Count, 10);
            Assert.AreEqual(typeof(DenseVector), vector.GetType());
            for (int i = 0; i < vector.Count; i++)
            {
                Assert.AreEqual(5.5, vector[i]);
            }

            vector = VectorBuilder.CreateVector(10, 5.5, VectorType.Sparse, false);
            Assert.AreEqual(vector.Count, 10);
            Assert.AreEqual(typeof(SparseVector), vector.GetType());
            for (int i = 0; i < vector.Count; i++)
            {
                Assert.AreEqual(5.5, vector[i]);
            }
        }

        [Test]
        public void CreateVectorArray()
        {
            double[] array = new double[] { 1, 2, 3, 4, 5 };

            Vector vector = VectorBuilder.CreateVector(array);
            Assert.AreEqual(vector.Count, array.Length);
            if (Settings.DefaultVectorType == VectorType.Dense)
            {
                Assert.AreEqual(typeof(DenseVector), vector.GetType());
            }

            if (Settings.DefaultVectorType == VectorType.Sparse)
            {
                Assert.AreEqual(typeof(SparseVector), vector.GetType());
            }

            for (int i = 0; i < vector.Count; i++)
            {
                Assert.AreEqual(array[i], vector[i]);
            }

            vector = VectorBuilder.CreateVector(array, VectorType.Dense);
            Assert.AreEqual(vector.Count, array.Length);
            Assert.AreEqual(typeof(DenseVector), vector.GetType());

            for (int i = 0; i < vector.Count; i++)
            {
                Assert.AreEqual(array[i], vector[i]);
            }

            vector = VectorBuilder.CreateVector(array, VectorType.Sparse);
            Assert.AreEqual(vector.Count, array.Length);
            Assert.AreEqual(typeof(SparseVector), vector.GetType());

            for (int i = 0; i < vector.Count; i++)
            {
                Assert.AreEqual(array[i], vector[i]);
            }

            vector = VectorBuilder.CreateVector(array, VectorType.Dense, true);
            Assert.AreEqual(vector.Count, array.Length);
            Assert.AreEqual(typeof(DenseVector), vector.GetType());

            for (int i = 0; i < vector.Count; i++)
            {
                Assert.AreEqual(array[i], vector[i]);
            }

            vector = VectorBuilder.CreateVector(array, VectorType.Sparse, true);
            Assert.AreEqual(vector.Count, array.Length);
            Assert.AreEqual(typeof(SparseVector), vector.GetType());

            for (int i = 0; i < vector.Count; i++)
            {
                Assert.AreEqual(array[i], vector[i]);
            }

            vector = VectorBuilder.CreateVector(array, VectorType.Dense, false);
            Assert.AreEqual(vector.Count, array.Length);
            Assert.AreEqual(typeof(DenseVector), vector.GetType());

            for (int i = 0; i < vector.Count; i++)
            {
                Assert.AreEqual(array[i], vector[i]);
            }

            vector = VectorBuilder.CreateVector(array, VectorType.Sparse, false);
            Assert.AreEqual(vector.Count, array.Length);
            Assert.AreEqual(typeof(SparseVector), vector.GetType());

            for (int i = 0; i < vector.Count; i++)
            {
                Assert.AreEqual(array[i], vector[i]);
            }
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void CreateVectorArrayNull()
        {
            double[] array = null;
            VectorBuilder.CreateVector(array);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void CreateVectorNotPositive()
        {
            VectorBuilder.CreateVector(0);
        }
    }
}
